{% extends '../base.html' %}
{% block css %}
<link href="/ttpstatic/css/experiment.css" rel="stylesheet" type="text/css"/>
<link href="/ttpstatic/css/dialog.css" rel="stylesheet" type="text/css"/>
{% comment %} <link rel="stylesheet" href="/ttpstatic/study/layui/css/layui.css" type="text/css"/> {% endcomment %}
<style>
  
</style>
{% endblock css %}

{% block content %}
<div id="experiment">
  <div class="header flex-row-between">
    <div>
      <img src='/ttpstatic/icon/e_logo.png' style="width: 24px; height: 25px; margin-right: 10px;" />
      <span>e安行实训平台</span>
    </div>
    <div class="flex-row-between">
      <span>用户：{{user}}</span>
    </div>
  </div>
  <div class="content flex-row-start">
    <div class="left">
      <p style="margin-bottom: 26px; width: 25vw;">学练课：{{experiment.experiment_name}}</p>
      <div class="tabBar flex-row-between">
        <div class="tabBar-item" onclick="onTab(0)">课程介绍</div>
        <div class="tabBar-item" onclick="onTab(1)">账号资源</div>
        <div class="tabBar-item" onclick="onTab(2)">学练手册</div>
      </div>
      <div class="intro">
        {% load markdownify %}
        {% autoescape off %}
          {{experiment.intro}}
        {% endautoescape %}
      </div>
      <div class="source-info">
        <div class="init-dialog">
          <p style="margin-top: 20px;padding-left: 20px;">本云主机开机密码</p>
          <div class="init-content" style="margin-top: 0;">
            <p style="width: 100%;height: 40px;line-height: 40px;background: #333333;padding: 0 20px !important;">Ad{r5@_d6dhnr</p>
          </div>
        </div>
      </div>
      <div class="step-info">
        <div class="step-header flex-row-between">
          <p id="step-header-title" class="step-header-title"></p>
          <img src='/ttpstatic/icon/list.png' style="width: 24px; height: 25px; cursor: pointer;" onclick="toggleStepList()" />
        </div>
        <div class="step-list">
          {% if describe_list|length > 0 %}
            {% for index, item in describe_list %}
              {% autoescape off %}
              <div class="step-item" onclick="changeListNew({{index}})">{{item.title}}</div>
              {% endautoescape %}
            {% endfor %}
          {% endif %}
        </div>
        <div id="step-content" class="step-content">
          <div id="step-detail" class="step-detail"></div>
        </div>
      </div>
      <div class="step-btn-bar">
        <div id="pre-btn" class="info-btn info-btn" onclick="onPre()">上一步</div>
        <div id="next-btn" class="main-btn" onclick="onNext()">下一步</div>
      </div>
      {% comment %} {% if experiment.instance.0.Status == 'UNCREATED' %}
      <div id="start-btn" class="l-btn" onclick="onCreate('{{experiment.instance.0.ImageId}}', this)">开始实验(时长: {{experiment.duration}}分钟)</div>
      {% elif experiment.instance.0.Status == 'STOPPED' %}
      <div class="l-btn" onclick="onInsAction('{{experiment.instance.0.InsId}}', 'start')">开始实验</div>
      {% else %}
      <div class="l-btn" style="background-color: #a6a6a6; cursor: not-allowed;">开始实验</div>
      {% endif %} {% endcomment %}
      <div class="unfold" onclick="onFold()">
        {% comment %} <i id="icon-unfold" class="layui-icon layui-icon-left" style="font-size: 30px; color: #666; line-height: 60px;"></i>  {% endcomment %}
        <img src='/ttpstatic/icon/unfold.png' />
        <span class="unfold-arrow">《</span>
      </div>
    </div>
    <div class="right">
      <div class="i-header flex-row-between">
        <div style="cursor: pointer;" onclick="toggleFullScreen()">
          <img id="full-screen-text" src='/ttpstatic/icon/full_screen.png' />
          <!-- <span id="full-screen-text">全屏</span> -->
        </div>
        <div class="running-block" style="font-size: 14px; display: none;">
          <span style="color: white;">学练时间剩余</span>
          <span id="cd-h"></span>: <span id="cd-m"></span>: <span id="cd-s"></span>
        </div>
        <div class="running-block" style="display: none;">
          <div id="net-btn" class="primary-btn" style="display: inline-block; background-color: #4C4C4C; color: #33FF81;" onclick="testNetSpeed('{{experiment.instance.0.PublicIpAddresses}}')">网络正常</div>
          <img src='/ttpstatic/icon/refresh.png' style="width: 24px; height: 24px; margin-left: 11px; cursor: pointer;" onclick="onRefreshVnc()" />
        </div>

        {% comment %} <div class="primary-btn"  onclick="onInsAction('{{experiment.instance.0.InsId}}', 'recovery', this)" style="display: inline-block; background-color: var(--main-color);">完成学练</div> {% endcomment %}
        <div class="primary-btn running-block" id="recovery" onclick="openComplete()" style="display: none; background-color: var(--main-color);">完成学练</div>

        <div id="can-trans-files" class="flex-row-between running-block" style="font-size: 14px; width: 110px; cursor: pointer; display: none;" onclick="toggleDrawerFile(publicIpAddresses)">
          <img src='/ttpstatic/icon/trans_file.png' />
          <span style="color: white;">传输文件</span>
        </div>
        <!--
        {% comment %} <div style="cursor: pointer;" onclick="onInsAction('{{experiment.instance.0.InsId}}', 'shutdown', this)"> {% endcomment %}
        <div class="running-block" style="cursor: pointer; display: none;" onclick="openQuit()">
          <img src='/static/icon/out.png' style="width: 20px; height: 24px; margin-left: 11px; cursor: pointer;" />
          <span>退出</span>
        </div>-->
      </div>
      <div id="i-content" class="i-content">
        {% comment %} {% if experiment.instance.0.Status == 'PENDING' or experiment.instance.0.Status == 'STARTING' %} {% endcomment %}
        <div id="starting-block" class="loading flex-column-center" style="display: none;">
          <img src='/ttpstatic/images/pc.png' />
          {% comment %} <p style="font-size: 16px; color: white">云教室电脑正在开机</p> {% endcomment %}
          <div class="flex-row-between" style="gap: 20px;">
            <div class="progress-bar">
              <div id="start-progress"></div>
            </div>
            <p id="start-text" style="font-size: 16px; color: white">30%</p>
          </div>
        </div>
        {% comment %} {% if experiment.instance.0.Status == 'STOPPING' %} {% endcomment %}
        <div id="stopping-block" class="loading flex-column-center" style="display: none;">
          <img src='/ttpstatic/images/connecting.png' />
          <p style="font-size: 16px; color: white">云教室电脑正在关机</p>
        </div>
        <iframe id="vnc_container" src="" width="100%" height="100%" style="display: none;"></iframe>
        <div id="uncreated-block" class="init-bar flex-column-center" style="display: none;">
          <div class="init-dialog">
            <p>本课程限时{{experiment.duration}}分钟</p>
            <div class="init-content">
              点击“开始学练”后，将为您提供虚拟资源供您使用。结束或退出学练后，虚拟资源及学练记录将被自动释放。
            </div>
          </div>
          <div id="start-btn" class="init-btn" onclick="onCreate('{{experiment.instance.0.ImageId}}', this)">开始学练</div>
        </div>
        <div id="stoped_block" class="init-bar flex-column-center" style="display: none;">
          <div class="init-dialog">
            <p>本课程限时{{experiment.duration}}分钟</p>
            <div class="init-content">
              点击“开始学练”后，将为您提供虚拟资源供您使用。结束或退出学练后，虚拟资源及学练记录将被自动释放。
            </div>
          </div>
          <div id="start-btn" class="init-btn" onclick="onStart()">开始学练</div>
        </div>
        <div class="drawer-file">
          <div class="drawer-tab flex-row-start">
            <div class="drawer-tabItem" onclick="onDrawerTab(0)">上传文件</div>
            <div class="drawer-tabItem" onclick="onDrawerTab(1)">导出文件</div>
          </div>
          <div class="drawer-upload">
            <div style="width: 550px;
            height: 50px;
            padding: 0 20px;
            background-color: #4C4C4C;
            font-size: 16px;
            color: white;
            line-height: 50px;
            align-items: center;">
              格式：.doc/.docx/.xls/.pdf/.txt
            </div>
            <div class="drawer-list-item flex-row-start">
              <img src='/ttpstatic/icon/pc_icon.png' style="margin-right: 10px;" />
              <span>本地文件上传</span>
              <button id="uploadButton" class="primary-btn" style="margin-left: auto;">立即上传</button>
              <input type="file" 
                id="fileInput" 
                style="display: none;" 
                accept=".doc,.docx,.xls,.pdf,.txt">
            </div>
          </div>
          <div class="drawer-export">
            <div class="export-bar flex-column-start">
              <p>选择要导出的文件</p>
              <p>1.将文件拖至桌面“文件中转站”；</p>
              <p>2.返回本页面，选择文件中转站中要导出的文件；</p>
              <p>3.点击“导出”按钮，将文件导出至本地。</p>
            </div>
            <div class="export-bar flex-column-start">
              <p>选择要导出的文件</p>
              <p style="color: var(--main-color);">仅支持导出以下格式文件：.doc/.docx/.xls/.pdf/.txt</p>
              <div id="files-options" style="max-height: 550px; overflow-y: auto;"></div>
              <div class="main-btn" onclick="downFiles(publicIpAddresses)">导出</div>
            </div>
          </div>
          <div class="drawer-footer-0 flex-row-start">
            <p>总空间：<span id="free-disk" style="color: var(--main-color)">200.00</span>可用/共<span id="total-disk">200</span></p>
            <p style="margin-left: auto;">单个文件最大<span style="color: var(--main-color)">100</span>MB</p>
          </div>
          <div class="drawer-footer-1 flex-row-start">
            <p>导出文件总大小不超过<span style="color: var(--main-color)">100</span>MB</p>
          </div>
        </div>
        {% comment %} dialog {% endcomment %}
        <div id="net-dialog" class="dialog" style="display: none;">
          <div class="dialog-header">
            <i id="isLoading" style="font-size: 26px;margin-right: 15px;" class="layui-icon layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop"></i>   
            <p id="net-speed-testing">网速检测中......</p>
            <img src='/ttpstatic/icon/close.png' style="margin-left: auto;" onclick="closeDialog()" />
          </div>
          <div class="dialog-info">
            <p id="download-text" style="color: #009DFF; display: none;">网络下载速度为0KB/S</p>
            <p id="upload-text" style="color: #009DFF; display: none;">网络上传速度为0KB/S</p>
            <p style="color: #009DFF;">若网速低于350KB/S，将影响您的使用体验</p>
          </div>
          <div class="dialog-footer">
            <div class="main-btn" onclick="closeDialog()">确定</div>
          </div>
        </div>
        {% comment %} 学练时间已到 {% endcomment %}
        <div id="out-dialog" class="dialog" style="display: none;">
          <div class="dialog-header">
            <p>学练结束</p>
          </div>
          <div class="dialog-info">
            <p style="color: #009DFF; font-size: 18px; font-weight: 700;">
              <img src='/ttpstatic/icon/bettery.png' style="margin-right: 15px;" />
              本次学练结束
            </p>
            <p>您的本次学练时间已达课程规定的{{experiment.duration}}分钟，学练资源将自动释放，感谢您的使用！</p>
          </div>
          <div class="dialog-footer">
            <div class="main-btn" onclick="onRecovery()">确定</div>
          </div>
        </div>
        {% comment %} 退出关闭实例 {% endcomment %}
<!--        <div id="dialogquit-dialog" class="dialog" style="display: none;">
          <div class="dialog-header">
            <p>确认退出</p>
          </div>
          <div class="dialog-info">
            <p style="color: #FF6200; font-size: 18px; font-weight: 700;">
              确认要退出吗？
            </p>
            <p>退出后，系统仍会为您保留已开通的云资源，您可以再次点击”开始学练“进行学习。</p>
          </div>
          <div class="dialog-footer">
            <div class="info-btn" style="margin-right: 15px; cursor: pointer;" onclick="closeDialog()">取消</div>
            <div class="main-btn" onclick="onShutdown()">确定</div>
          </div>
        </div>-->
        {% comment %} 完成学练 {% endcomment %}
        <div id="complete-dialog" class="dialog" style="display: none;">
          <div class="dialog-header">
            <p>完成确认</p>
          </div>
          <div class="dialog-info">
            <p style="color: #009DFF; font-size: 18px; font-weight: 700;">
              <img src='/ttpstatic/icon/complete.png' style="margin-right: 15px;" />
              恭喜您完成学练
            </p>
            <p>系统将释放已为您开通的云资源，您的学练状态将被标记为”已完成“，但学练记录不会被保存。</p>
          </div>
          <div class="dialog-footer">
            <div class="info-btn" style="margin-right: 15px; cursor: pointer;" onclick="closeDialog()">取消</div>
            <div class="main-btn" onclick="onRecovery()">确认完成</div>
          </div>
        </div>
        {% comment %} 连接中断提示 {% endcomment %}
        <div id="notice-dialog" class="dialog" style="display: none;">
          <div class="dialog-header">
            <p>创建远程连接会话失败</p>
          </div>
          <div class="dialog-info">
            <p style="color: #CC0000; font-size: 18px; font-weight: 700; text-align: center;">
              <img src='/ttpstatic/icon/notice.png' style="margin-right: 15px;" />
              连接失败
            </p>
            <p style="text-align: center;">请检查网络连接或者浏览器代理设置。</p>
          </div>
          <div class="dialog-footer" style="justify-content: center;">
            <div class="main-btn" onclick="location.reload()">重新连接</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
<div id="loading-bar" class="layui-progress" lay-filter="demo" lay-showPercent="true">
  <div class="layui-progress-bar" lay-percent="0%"></div>
</div>
<div id="dialog-mask" class="dialog-mask" style="display: none; width: 100vw; height: 100vh; position: fixed;"></div>
{% endblock content %}

{% block script %}
<script src="/ttpstatic/study/layui/layui.js" charset="utf-8"></script>
<script src="/ttpstatic/js/tools.js"></script>
{% comment %} <script src="/ttpstatic/js/experiment.js"></script> {% endcomment %}
{% comment %} <script src="https://cdn.jsdelivr.net/npm/js-base64@3.6.0/base64.min.js"></script> {% endcomment %}
<script>
  /*
  'UNCREATED': '未创建',
  'PENDING': '操作中..',
  'LAUNCH_FAILED': '创建失败',
  'RUNNING': '运行中..',
  'STOPPED': '关机',
  'STARTING': '开机中..',
  'STOPPING': '关机中..',
  'REBOOTING': '重启中..',
  'SHUTDOWN': '停止待销毁',
  'TERMINATING': '销毁中..'
  */
  let unfold = false
  let drawerShow = false
  let loading = false
  let novnc_url = ""
  var insId = ""
  let link_count = 0
  var start_pc = 0
  var calPending = 0;
  let isFullScreen = false
  let isStepList = false
  let canTransFile = false
  let isNetTesting = false
  let iscountDown = false
  var btnHanleing = false
  let describeList = []
  let selectedFiles = []
  var instanceData
  var layer
  var element
  var timerIn = null
  var publicIpAddresses = null
  var downloading = false
  var isLoading = true
  var currentStep = localStorage.getItem('currentStep')?localStorage.getItem('currentStep'):0
  var totalPage = 0
  var experiment_chapter = {}
  if(typeof layui === 'undefined') {
    location.reload()
  }
  layui.use('layer', function () {
    layer = layui.layer;
  });
  layui.use('element', function () {
    element = layui.element;
  });

  const copyContainer = document.getElementById('step-detail');

  copyContainer.addEventListener('copy', function(event) {
    layer.msg('信息已复制，请打开右侧远程桌面剪切板', {
      icon: 1,
      time: 1500 //2秒关闭（如果不配置，默认是3秒）
    }, function () {
    });
  });

  var iframeEl = document.getElementById("vnc_container");

  // 添加加载错误事件监听器
  iframeEl.addEventListener("load", function() {
    //console.log("iframe 加载成功");
  });

  iframeEl.addEventListener("error", function() {
    console.log("iframe 加载出错");
    // 在这里可以执行处理加载错误的代码
  });

  if({{error_code}} == -2) {
    debugger
    console.log('~error_code', {{error_code}})
    location.reload()
  }else if({{error_code}} == 2) {
    window.location.href = "/experiment/buy/" + {{experiment.id}} + "/"
  }
  
  window.onload = function() {
    
    //init
    let isConnect = false
    // startLoading(0)

    setTimeout(() => {
      if(!isConnect) {
        document.getElementById("notice-dialog").style.display = "block"
      }
    }, 5000)

    function onNetLink(ip) {
      //setTimeout(() => netLink(ip), 1500)
      setInterval(() => netLink(ip), 5 * 60 * 1000)
    }

    setTimeout(() => {
      instanceData = {{experiment.instance.0|safe}}
      insId = instanceData.InsId
      //init done
      // console.log('~views Status', instanceData)
      isConnect = true
      endLoading()
  
      function loadProgress () {
        if(start_pc < 7) {
          setTimeout(() => {
            document.getElementById('start-progress').style.width = 30 + start_pc * 10 + '%'
            document.getElementById('start-text').innerText= 30 + start_pc * 10 + '%'
            start_pc++
            loadProgress()
          }, 11000)
        }else if(start_pc >= 7) {
          //location.reload()
        }
      }
  
      function loadStopping () {
        if(start_pc < 5) {
          setTimeout(() => {
            start_pc++
            loadStopping()
          }, 2000)
        }else if(start_pc >= 5) {
          //location.reload()
        }
      }
  
      if(instanceData.Status == 'PENDING') {
        loadProgress()
      }else if(instanceData.Status == 'STOPPING' || instanceData.Status == 'STOPPING') {
        loadStopping()
      }else if(instanceData.Status == 'TERMINATING') {
        //location.reload()
      }
  
      let tabItem = document.getElementsByClassName("tabBar-item");
      tabItem[0].style.backgroundColor = "var(--main-color)";
      let drawTabItem = document.getElementsByClassName("drawer-tabItem");
      drawTabItem[0].style.color = "var(--main-color)";
      drawTabItem[0].style.borderBottom = "2px var(--main-color) solid";

  
      setTimeout(function () {
        if (window.navigator.userAgent.indexOf("JavaFX") >= 0) {
          logger(window.navigator.userAgent.indexOf("JavaFX"))
          logger(app.login.toString())
          // location.href = location.href 
        }
      }, 1000)

      if(localStorage.getItem("op-steps")) {
        let obj = JSON.parse(localStorage.getItem("op-steps"))
        if(obj[`${instanceData.ImageId}`] && obj[`${instanceData.ImageId}`].tab) {
          onTab(obj[`${instanceData.ImageId}`].tab)
        }else {
          onTab(0)
        }
      }
  
      function loadStatus () {
        var vmsStr = ""
        var id = {{ experiment.id }}
        //pending too long
        // timerIn = setInterval(() => {
        //   calPending+=7
        //   if(calPending == 70) {
        //     calPending = 0
        //     loadStatus()
        //   }
        //   /*
        //   if(calPending == 56) {
        //     location.reload()
        //   }
        //   */
        // }, 7000)
        //var vnccode = "{{vnccode}}"
        models.experimentModel.item({{experiment.id}}, function (res) {
          // calPending = 0
          // clearInterval(timerIn)
          // timerIn = null
          if (res.error_code == 0) {
            //instanceData = res.data.instance[0]
            instanceData.Status = res.data.instance[0].Status
            insId = res.data.instance[0].InsId
            publicIpAddresses = res.data.instance[0].PublicIpAddresses
            //vnc dom change
            if(res.data.instance[0].Status == 'UNCREATED' || res.data.instance[0].Status == 'TERMINATING') {
              document.getElementById('uncreated-block').style.display = "flex"
              document.getElementById('starting-block').style.display = "none"
              document.getElementById('stopping-block').style.display = "none"
              document.getElementById('vnc_container').style.display = "none"
              document.getElementById('stoped_block').style.display = "none"
              changeBlock('none')
            }else if(res.data.instance[0].Status == 'PENDING' || res.data.instance[0].Status == 'STARTING') {
              document.getElementById('uncreated-block').style.display = "none"
              document.getElementById('starting-block').style.display = "flex"
              document.getElementById('stopping-block').style.display = "none"
              document.getElementById('vnc_container').style.display = "none"
              document.getElementById('stoped_block').style.display = "none"
              changeBlock('none')
            }else if(res.data.instance[0].Status == 'RUNNING') {
              document.getElementById('uncreated-block').style.display = "none"
              document.getElementById('starting-block').style.display = "none"
              document.getElementById('stopping-block').style.display = "none"
              document.getElementById('vnc_container').style.display = "block"
              //document.getElementById('stoped_block').style.display = "none"
              changeBlock('block')
              start_pc = 0
            }else if(res.data.instance[0].Status == 'STOPPING') {
              document.getElementById('uncreated-block').style.display = "none"
              document.getElementById('starting-block').style.display = "none"
              document.getElementById('stopping-block').style.display = "flex"
              document.getElementById('vnc_container').style.display = "none"
              document.getElementById('stoped_block').style.display = "none"
              changeBlock('none')
            }else if(res.data.instance[0].Status == 'STOPPED') {
              document.getElementById('uncreated-block').style.display = "none"
              document.getElementById('starting-block').style.display = "none"
              document.getElementById('stopping-block').style.display = "none"
              document.getElementById('vnc_container').style.display = "none"
              document.getElementById('stoped_block').style.display = "flex"
              changeBlock('none')
            }
            
            //倒计时
            if (res.data.instance[0].Status == 'RUNNING' && document.getElementById('cd-h') && res.data.instance[0].create_st && !iscountDown) {
              //interval = setInterval(reverseTs, 1000);
              iscountDown = true;
              layui.use('util', function(){
                var util = layui.util;
                var endTime = localStorage.getItem("countdown-data") ? (JSON.parse(localStorage.getItem("countdown-data"))[res.data.instance[0].InsId]) : (new Date().getTime() + {{experiment.duration}} * 60 * 1000)
                //支持毫秒时间戳
                var serverTime = new Date().getTime();
                util.countdown(endTime, serverTime, function(date,serverTime,timer){
                  var str = date[0] + '天' + date[1] + '时' + date[2] + '分' + date[3]+'秒'
                  document.getElementById('cd-h').innerText = date[1] < 10 ?'0'+date[1]:date[1]
                  document.getElementById('cd-m').innerText = date[2] < 10 ?'0'+date[2]:date[2]
                  document.getElementById('cd-s').innerText = date[3] < 10 ?'0'+date[3]:date[3]
                  // 学练时间剩余0
                  if((date[1] == 0 && date[2] == 0 && date[3] == 1) || (endTime - serverTime < 0)){
                    document.getElementById('out-dialog').style.display = "block"
                    document.getElementById('dialog-mask').style.display = "block"
                    //setTimeout(() => onRecovery(), 10000)
                  }
                })
              })
            }
            //倒计时缓存
            if(res.data && res.data.instance[0].create_st) {
              //console.log('~create_st', new Date(res.data.instance[0].create_st).getTime())
              if(localStorage.getItem("countdown-data")) {
                let obj = JSON.parse(localStorage.getItem("countdown-data"))
                let timeLeft = new Date(res.data.instance[0].create_st).getTime() + ({{experiment.duration}} * 60 * 1000)
                obj[`${res.data.instance[0].InsId}`] = timeLeft
                localStorage.setItem("countdown-data", JSON.stringify(obj))
              }else {
                let obj = {}
                let timeLeft = new Date(res.data.instance[0].create_st).getTime() + ({{experiment.duration}} * 60 * 1000)
                obj[`${res.data.instance[0].InsId}`] = timeLeft
                localStorage.setItem("countdown-data", JSON.stringify(obj))
                location.reload()
              }
            }
            //console.log('~res.data', res.data)
            if(res.data.vnc_url && link_count == 0 && res.data.instance[0].Status == 'RUNNING') {
              //console.log('~res.data.vnc_url', res.data.vnc_url)
              let icd = res.data.instance[0].doraemon.slice(res.data.instance[0].doraemon.indexOf('A'), res.data.instance[0].doraemon.indexOf('nr') + 2)
              novnc_url = res.data.vnc_url + '?asd=&' + encodeURIComponent('abc=123@;hash&kk=替代方式$%^&pcode=' + res.data.instance[0].doraemon)
              autoGoVnc();
              link_count++;
            }
            if(!canTransFile && res.data.instance[0].Status == 'RUNNING') {
              //绑定虚拟机接口
              getDownloadFiles(res.data.instance[0].PublicIpAddresses)
              onUpload(res.data.instance[0].PublicIpAddresses)
              calVMDisk(res.data.instance[0].PublicIpAddresses)
              onNetLink(res.data.instance[0].PublicIpAddresses)
              //canTransFile = true
            }
            //console.log('~status', instanceData.Status)
            if((res.data.instance[0].Status == 'PENDING' || res.data.instance[0].Status == 'STARTING') && start_pc < 7) {
              // todo 类似应该封装，统一处理
              document.getElementById('start-progress').style.width = 30 + start_pc * 10 + '%'
              document.getElementById('start-text').innerText= 30 + start_pc * 10 + '%'
              start_pc ++
            }else if((res.data.instance[0].Status == 'PENDING' || res.data.instance[0].Status == 'STARTING') && start_pc >= 7) {
              //location.reload()
            }
            if(res.data.instance[0].Status == 'PENDING' || res.data.instance[0].Status == 'STARTING') {
              return setTimeout(function () {
                loadStatus()
              }, 3000)
            }
            if(!res.data.vnc_url && instanceData.Status == 'RUNNING'){
              return setTimeout(function () {
                loadStatus()
              }, 10000) 
            }else if(!res.data.vnc_url && instanceData.Status == 'UNCREATED') {
              return setTimeout(function () {
                loadStatus()
              }, 10000)
            }
          }else {
            console.log('no res')
          }
          return setTimeout(function () {
            loadStatus()
          }, 10000)
        }, function (err) {
          console.log('~loadStatus err', err)
          // calPending = 0
          // clearInterval(timerIn)
          if(err.error_code) {
            //location.reload()
            return setTimeout(function () {
              loadStatus()
            }, 3000)
          }
        })
      }

      loadStatus()
    }, 100) //guowei 3000=>100
  }

  function onCreate(ImageId, node) {
    console.log(ImageId, event)
    if (loading) return;
    if (btnHanleing) return;
    startLoading(0)
    btnHanleing = true
    let opsEl = document.getElementById('start-btn')
    opsEl.style.cursor = "not-allowed"
    models.insModel.action({
      action: 'create',
      imageId: ImageId,
      envId: {{ experiment.environment.id }}
    }, function(res) {
      console.log('~create res', res)
      endLoading()
      document.getElementById('uncreated-block').style.display = "none"
      document.getElementById('starting-block').style.display = "flex"
      opsEl.style.cursor = "pointer"
      btnHanleing = false
      let nextBtn = document.getElementById('next-btn')
      if(nextBtn.innerHTML == '完成') {
        nextBtn.setAttribute('onclick', `openComplete()`)
      }
      //location.reload()
    }, function(err) {
      endLoading()
      layer.msg(err.message, {
        icon: 1,
        time: 3000 //2秒关闭（如果不配置，默认是3秒）
      }, function () {
        opsEl.style.cursor = "pointer"
        btnHanleing = false
      });
    })
  }
  
  function onInsAction(InsId, action, node) {
    console.log(InsId, event)
    //not-allowed
    if (loading) return;
    if (btnHanleing) return;
    layer.confirm(`确定${action}虚拟机实例？`, { title: '提示' }, function (index) {
      startLoading(index)
      models.insModel.action({
        action: action,
        insId: InsId,
        envId: {{ experiment.environment.id }}
      }, function(res) {
        endLoading()
        let opsEls = document.getElementsByClassName('btn-short')
        for(let el of opsEls) {
          el.style.cursor = "not-allowed"
          el.style.backgroundColor = "#e6e6e6"
        }
        btnHanleing = true
        // todo 延时3秒完成
        layer.msg(action + `成功，${action == 'start' ? '15' : '3'}秒后刷新页面`, {
          icon: 1,
          time: action == 'start' ? 15000 : 5000 //2秒关闭（如果不配置，默认是3秒）
        }, function () {
          setTimeout(() => location.reload(), action == 'start' ? 15000 : 5000)
          // location.href = location.href + "#login-vm"
        });
      }, function(err) {
        endLoading()
        layer.msg(err.message, {
          icon: 1,
          time: 5000 //2秒关闭（如果不配置，默认是3秒）
        }, function () {
        });
      })
        }, function(cancel) {
        loading = false
        console.log('cancel', cancel)
      })
  }

  function testNetSpeed(ip) {
    document.getElementById("net-dialog").style.display = "block"
    document.getElementById("download-text").style.display = "none"
    document.getElementById("upload-text").style.display = "none"
    document.getElementById("net-speed-testing").innerHTML = "网速检测中......"
    if(!isNetTesting) {
      netLink(ip)
    }
  }

  function closeDialog() {
    document.getElementById("net-dialog").style.display = "none"
    document.getElementById("out-dialog").style.display = "none"
    //document.getElementById("quit-dialog").style.display = "none"
    document.getElementById("complete-dialog").style.display = "none"
  }

/*  function openQuit() {
    document.getElementById("quit-dialog").style.display = "block"
  }*/

  function openComplete() {
    document.getElementById("complete-dialog").style.display = "block"
  }

  function onShutdown() {
    /*let instanceData = {{experiment.instance.0|safe}}; */
    startLoading(0)
    closeDialog()
    models.insModel.action({
      action: 'shutdown',
      insId: insId,
      envId: {{ experiment.environment.id }}
    }, function(res) {
      endLoading()
      document.getElementById('stopping-block').style.display = "flex"
      document.getElementById('vnc_container').style.display = "none"
      changeBlock('none')
      document.getElementsByClassName('drawer-file ')[0].style.width = '0'
      drawerShow = false
    }, function(err) {
      endLoading()
      layer.msg(err.message, {
        icon: 1,
        time: 3000 //2秒关闭（如果不配置，默认是3秒）
      }, function () {
        //setTimeout(() => location.reload(), 10000)
      });
    })
  }

  function onStart() {
    {#let instanceData = {{experiment.instance.0|safe}};#}
    startLoading(0)
    link_count = 0;
    models.insModel.action({
      action: 'start',
      insId: insId,
      envId: {{ experiment.environment.id }}
    }, function(res) {
      endLoading()
      document.getElementById('starting-block').style.display = "flex"
      //document.getElementById('stoped-block').style.display = "none"
      start_pc = 5
    }, function(err) {
      endLoading()
      layer.msg(err.message, {
        icon: 1,
        time: 3000 //2秒关闭（如果不配置，默认是3秒）
      }, function () {
        //setTimeout(() => location.reload(), 10000)
      });
    })
  }

  function onRecovery() {
    startLoading(0)
    drawerShow = false
    document.getElementsByClassName('drawer-file ')[0].style.width = '0'
    {#let instanceData = {{experiment.instance.0|safe}};#}
    closeDialog()
    link_count = 0;
    layer.msg('正在关闭远程桌面连接，请稍后', {
      icon: 1,
      time: 3000 //2秒关闭（如果不配置，默认是3秒）
    }, function () {
    });
    nullFunction = function () {}
    let recoveryBtn = document.getElementById('recovery')
    recoveryBtn.style.cursor = "not-allowed"
    recoveryBtn.onclick = nullFunction;
    models.insModel.action({
      action: 'recovery',
      insId: insId,
      envId: {{ experiment.environment.id }}
    }, function(res) {
      endLoading()
      if(document.getElementById('vnc_container'))document.getElementById('vnc_container').style.display = "none"
      if(document.getElementById('stoped-block'))document.getElementById('stoped-block').style.display = "none"
      document.getElementById('uncreated-block').style.display = "flex"
      changeBlock('none')
      document.getElementsByClassName('drawer-file ')[0].style.width = '0'
      drawerShow = false
      document.getElementById('dialog-mask').style.display = "none"
      recoveryBtn.style.cursor = "pointer"
      recoveryBtn.onclick = openComplete;
      let nextBtn = document.getElementById('next-btn')
      if(nextBtn.innerHTML == '完成') {
        nextBtn.setAttribute('onclick', ``)
      }
    }, function(err) {
      endLoading()
      layer.msg(err.message, {
        icon: 1,
        time: 3000 //2秒关闭（如果不配置，默认是3秒）
      }, function () {
          recoveryBtn.style.cursor = "pointer"
          recoveryBtn.onclick = openComplete;
        //setTimeout(() => location.reload(), 10000)
      });
    })
  }

  function changeBlock(status) {
    let runningELs = document.getElementsByClassName('running-block')
    //console.log('~runningELs', runningELs)
    if(runningELs.length) {
      for(let i = 0; i < runningELs.length; i++) {
        document.getElementsByClassName('running-block')[i].style.display = status
      }
    }
  }

  {% comment %} experiment.js {% endcomment %}
  function onTab(tab) {
    let tabItem = document.getElementsByClassName('tabBar-item')
    let intro = document.getElementsByClassName('intro')
    let sourceInfo = document.getElementsByClassName('source-info')
    let stepInfo = document.getElementsByClassName('step-info')
    let stepBtnBar = document.getElementsByClassName('step-btn-bar')
    
    let instanceData = {{experiment.instance.0|safe}};
    if(tab==0) {
      tabItem[1].style.backgroundColor = 'unset'
      tabItem[2].style.backgroundColor = 'unset'
      intro[0].style.display = 'block'
      sourceInfo[0].style.display = 'none'
      stepInfo[0].style.display = 'none'
      stepBtnBar[0].style.display = 'none'
    }else if(tab==1){
      tabItem[0].style.backgroundColor = 'unset'
      tabItem[2].style.backgroundColor = 'unset'
      intro[0].style.display = 'none'
      sourceInfo[0].style.display = 'block'
      stepInfo[0].style.display = 'none'
      stepBtnBar[0].style.display = 'none'
    }else {
      tabItem[0].style.backgroundColor = 'unset'
      tabItem[1].style.backgroundColor = 'unset'
      sourceInfo[0].style.display = 'none'
      stepInfo[0].style.display = 'block'
      intro[0].style.display = 'none'
      stepBtnBar[0].style.display = 'flex'
      loadContent()
      getStyle()
    }
    tabItem[tab].style.backgroundColor = '#FF6200'
    if(localStorage.getItem("op-steps")) {
      let obj = JSON.parse(localStorage.getItem("op-steps"))
      obj[`${instanceData.ImageId}`] = {...obj[`${instanceData.ImageId}`], tab }
      localStorage.setItem("op-steps", JSON.stringify(obj))
    }else {
      let obj = {}
      obj[`${instanceData.ImageId}`] = {tab}
      localStorage.setItem("op-steps", JSON.stringify(obj))
    }
  }
  let preBtn = document.getElementById('pre-btn')
  let nextBtn = document.getElementById('next-btn')
  function onPre(){
    if(currentStep<=0){
      layer.msg('当前为第一步', {
        icon:1,
        time: 3000 //2秒关闭（如果不配置，默认是3秒）
      }, function () {
      });
      currentStep = 0
    }else{
      currentStep--
      loadContent()
      localStorage.setItem('currentStep', currentStep)
    }
    getStyle()
  }
  function onNext(){
    currentStep++
    localStorage.setItem('currentStep', currentStep)
    if(currentStep+1>totalPage){
      layer.msg('当前为最后一步', {
        icon:1,
        time: 3000 //2秒关闭（如果不配置，默认是3秒）
      }, function () {
      });
      currentStep = totalPage-1
      localStorage.setItem('currentStep', currentStep)
    }else{
      loadContent()
    }
    getStyle()
  }
  var scrollTop = 0
  function getStyle(){
    if(currentStep>0){
      nextBtn.classList.add('main-btn')
      preBtn.classList.add('main-btn')
      preBtn.classList.remove('info-btn')
    }
    if(currentStep<totalPage-1){
      nextBtn.classList.add('main-btn')
      nextBtn.classList.remove('info-btn')
    }
    if(currentStep==totalPage-1){
      preBtn.classList.add('main-btn')
      nextBtn.classList.add('info-btn')
      preBtn.classList.remove('info-btn')
      nextBtn.classList.remove('main-btn')
    }
    if(currentStep==0){
      preBtn.classList.add('info-btn')
      nextBtn.classList.add('main-btn')
      preBtn.classList.remove('main-btn')
      nextBtn.classList.remove('info-btn')
    }
    // document.getElementById('step-content').scrollTop = 10
    document.getElementById('step-content').scrollTo({
      top: 10,
      behavior: 'smooth' // 用于实现平滑滚动效果，注意并非所有浏览器都支持
    });
  }
  function changeListNew(index){
    isStepList = false
    currentStep = index
    localStorage.setItem('currentStep', currentStep)
    getStyle()
    loadContent()
    document.getElementsByClassName('step-list')[0].style.display = 'none';
    var stepLists = document.getElementsByClassName('step-list');
    var stepItems = stepLists[0].getElementsByClassName('step-item');
    for (var i = 0; i < stepItems.length; i++) {
      if(i == currentStep){
        stepItems[i].style.background = '#665347';
        stepItems[i].style.color = 'var(--main-color)';
      }else{
        stepItems[i].style.background = '';
        stepItems[i].style.color = '';
      }
    }
  }
  
  function loadContent(){
    models.experimentModel.paginationList({{experiment.id}}+'/'+currentStep, function (res) {
      if(res.code == 200){
        experiment_chapter = res.experiment_chapter;
        totalPage = res.experiment_chapter.pages;
        document.getElementById("step-detail").innerHTML = experiment_chapter.detail
        document.getElementById("step-header-title").innerHTML = experiment_chapter.title_list[currentStep].title
        var stepLists = document.getElementsByClassName('step-list');
        var stepItems = stepLists[0].getElementsByClassName('step-item');
        for (var i = 0; i < stepItems.length; i++) {
          if(i == currentStep){
            stepItems[i].style.background = '#665347';
            stepItems[i].style.color = 'var(--main-color)';
          }else{
            stepItems[i].style.background = '';
            stepItems[i].style.color = '';
            
          }
        }
      }
    }, function(err) {
      onRefreshVnc()
    })
  }
  function onFold() {
    // let classVal = document.getElementById("icon-unfold");
    if(!unfold) {
      document.getElementsByClassName('left')[0].style.width = '0'
      document.getElementsByClassName('unfold')[0].style.left = '40px'
      document.getElementsByClassName('right')[0].style.width = '100vw'
      document.getElementsByClassName('unfold-arrow')[0].innerHTML = "》"
      // classVal.classList.remove('layui-icon-left')
      // classVal.classList.add('layui-icon-right')
      // classVal.style.marginLeft = '7px'
    }else {
      document.getElementsByClassName('left')[0].style.width = '25vw'
      document.getElementsByClassName('unfold')[0].style.left = 'calc(25vw + 40px)'
      document.getElementsByClassName('right')[0].style.width = 'calc(75vw - 66px)'
      document.getElementsByClassName('unfold-arrow')[0].innerHTML = "《"
      // classVal.classList.remove('layui-icon-right')
      // classVal.classList.add('layui-icon-left')
      // classVal.style.marginLeft = '0'
    }
    unfold = !unfold;
  }
  
  function startLoading(index) {
    loading = true
    layer.close(index)
      setTimeout(function() {
          //  element.progress('demo', '50%')
          element.progress('demo', '100%') //guowei  50%=>100%
      }, 1000)
  }
  
  function endLoading() {
    element.progress('demo', '100%')
    loading = false
    window.setTimeout(function () {
      element.progress('demo', '0%')
    }, 3000)
  }
  
  function reload() {
    location.href = location.href + "#login-vm"
  }
  
  function logger(msg) {
    let n = document.getElementById("logger");
    if (n) {
      let p = n.innerHTML;
      n.innerHTML = p + "<p>" + msg + "</p>"
      console.log(msg)
    }
  }
  
  function autoGoVnc() {
    logger("goVNC")
    try {
      if (window.app || typeof app != "undefined") {
        logger("go app.login")
        try {
          app.login(id, pwd)
        } catch (e) {
          logger(e.toString())
        }
      } else {
        // debugger
        let vnc_display = document.getElementById('vnc_container');
        console.log(novnc_url)
        vnc_display.src = novnc_url;

      }
    }catch (e) {
      logger(e.toString())
    }
    return
  }
  
  function toggleFullScreen() {
    let text = document.getElementById("full-screen-text");
    if (document.fullscreenElement) {
      isFullScreen = false
      text.innerHTML = "全屏"
      // 退出全屏
      document.exitFullscreen()
        .then(() => {
          //console.log('退出全屏成功');
          unfold = true
          onFold()
          document.getElementsByClassName('left')[0].style.width = '25vw'
          document.getElementsByClassName('unfold')[0].style.left = 'calc(25vw + 40px)'
          document.getElementsByClassName('right')[0].style.width = 'calc(75vw - 66px)'
          document.getElementsByClassName('header')[0].style.display = 'flex'
          document.getElementsByClassName('content')[0].style.height = 'calc(100% - 55px)'
        })
        .catch((error) => {
            console.error('退出全屏失败', error);
        });
    } else {
      isFullScreen = true
      text.innerHTML = "退出全屏"
      // 进入全屏
      document.documentElement.requestFullscreen()
        .then(() => {
          //console.log('进入全屏成功');
          document.getElementsByClassName('left')[0].style.width = '0'
          document.getElementsByClassName('unfold')[0].style.left = '40px'
          document.getElementsByClassName('right')[0].style.width = '100%'
          document.getElementsByClassName('header')[0].style.display = 'none'
          document.getElementsByClassName('content')[0].style.height = '100%'
        })
        .catch((error) => {
            console.error('进入全屏失败', error);
        });
    }
    if(!unfold){
        onFold();
    }
  }
  
  function toggleStepList() {
    if(!isStepList) {
      isStepList = true
      document.getElementsByClassName('step-list')[0].style.display = 'block'
    }else {
      isStepList = false
      document.getElementsByClassName('step-list')[0].style.display = 'none'
    }
  }
  
  function changeList(index, arr = describeList, startData = insId, status = instanceData.Status) {
    //console.log(status, instanceData.Status)
    isStepList = false
    document.getElementsByClassName('step-list')[0].style.display = 'none'
    // if(!arr)arr = describeList
    // list item style
    if(arr.length) {
      arr.forEach((item, key) => {
        if(key == index) {
          document.getElementsByClassName('step-item')[index].style.color = "var(--main-color)"
          document.getElementsByClassName('step-item')[index].style.backgroundColor = "#665347"
          document.getElementsByClassName('step-header-title')[0].innerHTML = arr[index].title
          document.getElementsByClassName('step-detail')[0].innerHTML = arr[index].detail
        }else {
          document.getElementsByClassName('step-item')[key].style.color = "white"
          document.getElementsByClassName('step-item')[key].style.backgroundColor = "unset"
        }
      })
    }
    // pre, next btn
    let preBtn = document.getElementById('pre-btn')
    let nextBtn = document.getElementById('next-btn')
    if(index == 0 && arr.length != 1) {
      preBtn.classList.add('info-btn')
      nextBtn.classList.add('main-btn')
      preBtn.classList.remove('main-btn')
      nextBtn.classList.remove('info-btn')
      nextBtn.setAttribute('onclick', `changeList(${index + 1}, ${JSON.stringify(arr)}, '${startData}')`, status)
      /*nextBtn.innerHTML = '下一步'*/
    }else if(index == 0 && arr.length == 1) {
      nextBtn.classList.add('info-btn')
      preBtn.classList.remove('info-btn')
      /*preBtn.innerHTML = ""*/
      nextBtn.classList.remove('main-btn')
      nextBtn.setAttribute('onclick', ``)
/*      if(status != "UNCREATED") {
        nextBtn.setAttribute('onclick', `openComplete()`)
      }else {
        nextBtn.setAttribute('onclick', ``)
      }

      nextBtn.innerHTML = '完成'*/
    }else if(index == (arr.length - 1)) {
      preBtn.classList.add('main-btn')
      nextBtn.classList.add('info-btn')
      preBtn.classList.remove('info-btn')
      nextBtn.classList.remove('main-btn')
      preBtn.setAttribute('onclick', `changeList(${index - 1}, ${JSON.stringify(arr)}, '${startData}')`, status)
/*      if(status != "UNCREATED") {
        nextBtn.setAttribute('onclick', `openComplete()`)
      }else {
        nextBtn.setAttribute('onclick', ``)
      }
      nextBtn.innerHTML = '完成'*/
    }else {
      preBtn.classList.add('main-btn')
      nextBtn.classList.add('main-btn')
      preBtn.classList.remove('info-btn')
      nextBtn.classList.remove('info-btn')
      preBtn.setAttribute('onclick', `changeList(${index - 1}, ${JSON.stringify(arr)}, '${startData}')`, status)
      nextBtn.setAttribute('onclick', `changeList(${index + 1}, ${JSON.stringify(arr)}, '${startData}')`, status)
      /*nextBtn.innerHTML = '下一步'*/
    }
    if(localStorage.getItem("op-steps")) {
      let obj = JSON.parse(localStorage.getItem("op-steps"))
      obj[`${instanceData.ImageId}`] = {...obj[`${instanceData.ImageId}`], page: index + 1 }
      localStorage.setItem("op-steps", JSON.stringify(obj))
    }else {
      let obj = {}
      obj[`${instanceData.ImageId}`] = {page: index + 1}
      localStorage.setItem("op-steps", JSON.stringify(obj))
    }
  }
  
  function onDrawerTab(tab) {
    let tabItem = document.getElementsByClassName('drawer-tabItem')
    if(!tab) {
      tabItem[1].style.color = 'white'
      tabItem[1].style.borderBottom = '2px #333333 solid'
      document.getElementsByClassName('drawer-export')[0].style.display = 'none'
      document.getElementsByClassName('drawer-upload')[0].style.display = 'block'
      document.getElementsByClassName('drawer-footer-0')[0].style.display = 'flex'
      document.getElementsByClassName('drawer-footer-1')[0].style.display = 'none'
    }else {
      tabItem[0].style.color = 'white'
      tabItem[0].style.borderBottom = '2px #333333 solid'
      document.getElementsByClassName('drawer-upload')[0].style.display = 'none'
      document.getElementsByClassName('drawer-export')[0].style.display = 'block'
      document.getElementsByClassName('drawer-footer-0')[0].style.display = 'none'
      document.getElementsByClassName('drawer-footer-1')[0].style.display = 'block'
    }
    tabItem[tab].style.color = '#FF6200'
    tabItem[tab].style.borderBottom = '2px #FF6200 solid'
  }
  
  function toggleDrawerFile(ip) {
    if(!drawerShow) {
      getDownloadFiles(ip)
      document.getElementsByClassName('drawer-file ')[0].style.width = '550px'
    }else {
      document.getElementsByClassName('drawer-file ')[0].style.width = '0'
    }
    drawerShow = !drawerShow;
  }
  
  function calVMDisk(ip) {
    fetch(`/ttp/api/stu/experiment/df-h/?ip=${ip}&port=7079`).then(response => {
      if (!response.ok) {
        throw new Error('网络请求失败');
      }
      return response.json(); // 解析响应为 JSON 数据
    }).then(res => {
      // 在这里处理获取的数据
      // console.log('~disk', res);
      if(res.data.total) {
        document.getElementById("free-disk").innerHTML = res.data.total.free + 'GB'
        document.getElementById("total-disk").innerHTML = res.data.total.total + 'GB'
      }
    })
    .catch(error => {
      // 处理请求失败
      console.error(error);
    });
  }
  
  function netLink(ip) {
    isNetTesting = true
    //`http://${ip}:7079/test-internet-speed`
    fetch(`/ttp/api/stu/experiment/test-speed`).then(response => {
      if (!response.ok) {
        throw new Error('网络请求失败');
      }
      return response.json(); // 解析响应为 JSON 数据
    }).then(res => {
      // 在这里处理获取的数据
      // console.log('~net linking', res);
      document.getElementById("isLoading").style.display = "block"
      if(res.data) {
        document.getElementById("net-btn").style.display = "inline-block"
          download_speed = false
        var downloadSpeedString = res.data.download_speed.toString();
        if (downloadSpeedString.includes("bps")) {
          download_speed = true
        }
        if (downloadSpeedString.includes("Kbps")) {
          download_speed = parseFloat(res.data.download_speed.slice(0, -4))<=350;
        }
        if (downloadSpeedString.includes("Mbps")) {
          download_speed = parseFloat(res.data.download_speed.slice(0, -4))<2.8;
        }
        if(download_speed) {
          document.getElementById("net-btn").style.color = "#FF0000"
          document.getElementById("net-btn").style.backgroundColor = "white"
          document.getElementById("net-btn").innerHTML = "网络繁忙"
        }else {
          document.getElementById("net-btn").style.color = "#33FF81"
          document.getElementById("net-btn").style.backgroundColor = "#4C4C4C"
          document.getElementById("net-btn").innerHTML = "网络正常"
        }
        document.getElementById("download-text").style.display = "block"
        document.getElementById("download-text").innerHTML = `网络下载速度为${res.data.download_speed}`
        document.getElementById("upload-text").style.display = "block"
        document.getElementById("upload-text").innerHTML = `网络上传速度为${res.data.upload_speed}`
        document.getElementById("net-speed-testing").innerHTML = "检测完成"
        document.getElementById("isLoading").style.display = "none"
      }else {
        document.getElementById("net-dialog").style.display = "none"
        layer.alert('网速测试出问题了，请关闭等会儿再试试~', {icon: 3})
      }
      isNetTesting = false
    })
    .catch(error => {
      // 处理请求失败
      console.error(error);
      isNetTesting = false
    });
  }
  
  function getDownloadFiles(ip) {
    models.vmTransFileModel.fileList({ip}, function(res) {
      //console.log('~download files', res)
      canTransFile = true
      let arr = res.data.file_transfer_station_files
  
      let optionsContainer = document.getElementById('files-options');
      while (optionsContainer.firstChild) {
        optionsContainer.removeChild(optionsContainer.firstChild);
      }

      // 渲染动态选项
      arr.forEach(function(item) {
        let box = document.createElement('div');
        box.style.marginBottom = '10px'
        let checkbox = document.createElement('input');
        checkbox.style.marginRight = '15px'
        checkbox.type = 'checkbox';
        checkbox.name = 'files-option';
        checkbox.value = item;
        box.appendChild(checkbox);
  
        let label = document.createElement('label');
        label.textContent = item;
        box.appendChild(label);
  
        optionsContainer.appendChild(box);
        
        // 添加事件监听器，监听选择
        checkbox.addEventListener('change', function(e) {
          //console.log('~~~e', e.target.value)
          let selectValue = e.target.value
          /*
          if (checkbox.checked) {
              console.log('download-files选择了：' + item.value);
          }
          */
          if(!selectedFiles.includes(selectValue)) {
            selectedFiles.push(selectValue)
          }else {
            let idx = selectedFiles.indexOf(selectValue)
            selectedFiles.splice(idx, 1)
          }
          //console.log('~~~selectedFiles', selectedFiles)
        });
      });
      let transDom = document.getElementById("can-trans-files");
      transDom.style.display = "block"
    }, function(err) {
      console.log('~download files failed', err)
    })
  }
  
  function downFiles(ip) {
    if(selectedFiles.length == 0) {
      layer.msg('没有选择到要下载的文件。', {
        icon: 2,
        time: 1500 //2秒关闭（如果不配置，默认是3秒）
      }, function () {
      });
      return
    }
    if(downloading) {
      return;
    }
    startLoading(0)
    downloading = true
    let fileName;
    // 假设服务器返回的响应是blob对象
    fetch(`/ttp/api/stu/experiment/file-download/?ip=${ip}&fileName=` + (selectedFiles.length > 1 ? selectedFiles.join(',') : selectedFiles[0]))
    {#fetch(`https://${ip}:7079/file-download?fileName=` + (selectedFiles.length > 1 ? selectedFiles.join(',') : selectedFiles[0]))#}
        .then(response => {
    const fileSize = response.headers.get('Content-Length');
    fileName = response.headers.get('Content-Disposition').split(";")[1].split("=")[1].trim().slice(1,-1);
    if (fileSize && parseFloat(fileSize) > 100*1024*1024) {
      throw new Error('导出文件的总大小不能超过100MB');
    }
    return response.blob();
  })
     // .then(response => response.blob())
      .then(blob => {
        // 创建一个blob URL并生成下载链接
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        console.log(url)
        console.log(selectedFiles)
        a.download = selectedFiles.length > 1 ? fileName : selectedFiles[0]; // 设置下载的文件名和扩展名
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
        //下载完成
        selectedFiles = []
        toggleDrawerFile(ip)
        layer.msg('文件下载成功！', {
          icon: 1,
          time: 3000 //2秒关闭（如果不配置，默认是3秒）
        }, function () {
          downloading = false
          endLoading()
        });
      })
      .catch(error => {
        downloading = false
        endLoading()
          //console.error('下载出错：', error);
        // 显示错误提示
      layer.msg(error.message, {
          icon: 2,
      time: 3000
    });
      });
  }

  function getCookie(name) {
  const cookieValue = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
  return cookieValue ? cookieValue[2] : null;
}
  function onUpload(ip) {
    // 获取文件输入框和上传按钮
    let fileInput = document.getElementById('fileInput');
    let uploadButton = document.getElementById('uploadButton');
  
    // 添加点击事件监听器
    uploadButton.addEventListener('click', function() {
      // 触发文件选择对话框
      fileInput.click();
    });

    // 文件选择事件监听器
    fileInput.addEventListener('change', function() {
        const selectedFile = fileInput.files[0];
        const maxSizeInBytes = 100 * 1024 * 1024; // 100MB
        var index= selectedFile.name.lastIndexOf(".");//获取最后一个.的位置
        var ext = selectedFile.name.substr(index+1);//获取后缀
        var pattern = /^(txt|doc|docx|pdf|xls)$/;
        if(!pattern.test(ext))
        {
          layer.alert('可支持上传的文件格式：.doc/.docx/.xls/.pdf/.txt', {icon: 3});
          return false;
        }
        if (selectedFile.size > maxSizeInBytes) {
          layer.alert('上传文件已超过100MB，请重新选择文件', {icon: 3})
          return
        }
        console.log('~~~file', fileInput.files[0])
        if (selectedFile) {
            // 创建一个 FormData 对象
            let formData = new FormData();
  
            // 将文件添加到 FormData，参数名为 "file"
            formData.append('file', selectedFile);
  
            // 执行上传操作（你需要将这里的URL替换为实际的上传地址）
            //let uploadUrl = `https://${ip}:7079/file-upload`; // 替换为实际的上传URL
            let uploadUrl = `/ttp/api/stu/experiment/file-upload/${ip}`;
            let xhr = new XMLHttpRequest();
            // 获取 CSRF 令牌的值
            const csrfToken = getCookie('csrftoken');
            console.log("experiment.html")
            console.log(csrfToken)
            xhr.open('POST', uploadUrl, true);
            xhr.setRequestHeader('X-CSRFToken',csrfToken)
            xhr.send(formData);
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    toggleDrawerFile(ip)
                    layer.msg('文件上传成功！', {
                      icon: 1,
                      time: 1500
                    }, function () {
                      /*
                      document.getElementsByClassName('drawer-file')[0].style.width = '0'
                      drawerShow = !drawerShow;
                      */
                    });
                } else if (xhr.status !== 200) {
                    layer.alert('文件上传失败！', {icon: 3});
                }
            };
        } else {
            layer.alert('没有选择到文件或出问题了。', {icon: 3});
        }
    });
  }

  function onRefreshVnc() {
    startLoading(0)
    models.experimentModel.item({{experiment.id}}, function (res) {
      if(res.data.vnc_url && res.data.instance[0].Status == 'RUNNING') {
        //console.log('~res.data.vnc_url', res.data.vnc_url)
        let icd = res.data.instance[0].doraemon.slice(res.data.instance[0].doraemon.indexOf('A'), res.data.instance[0].doraemon.indexOf('nr') + 2)
        novnc_url = res.data.vnc_url + '?asd=&' + encodeURIComponent('abc=123@;hash&kk=替代方式$%^&pcode=' + res.data.instance[0].doraemon)
        autoGoVnc();
        endLoading()
      }
    }, function(err) {
      onRefreshVnc()
    })
  }
  window.onresize = function() {
    const isFullScreen = document.fullscreenElement
    if (isFullScreen) {
      onFold()
      unfold = true
      document.getElementsByClassName('left')[0].style.width = '0'
      document.getElementsByClassName('unfold')[0].style.left = '40px'
      document.getElementsByClassName('right')[0].style.width = '100%'
      document.getElementsByClassName('header')[0].style.display = 'none'
      document.getElementsByClassName('content')[0].style.height = '100%'
    } else {
      document.getElementsByClassName('left')[0].style.width = '25vw'
      document.getElementsByClassName('unfold')[0].style.left = 'calc(25vw + 40px)'
      document.getElementsByClassName('right')[0].style.width = 'calc(75vw - 66px)'
      document.getElementsByClassName('header')[0].style.display = 'flex'
      document.getElementsByClassName('content')[0].style.height = 'calc(100% - 55px)'
    }

  }

</script>
{% endblock script %}